package top.lixunda.books3.util;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Random;

@Component
public class VerifyCode {

	@Value("100")
	private int weight;
	@Value("50")
	private int height=50;

	@Value("6")
	private int lineNumber = 6;
	@Value("4")
	private int charCount = 4;

	@Value("-1")
	private int r = -1;
	@Value("-1")
	private int g = -1;
	@Value("-1")
	private int b = -1;

    private int size = 25;

	private Random random=new Random();
	private String[] fontNames={"宋体","华文楷体", "黑体", "微软雅黑", "楷体_GB2312"};
	private String codes="23456789abcdefghjkmnopqrstuvwxyzABCDEFGHJKMNPQRSTUVWXYZ";

	
	public int getWeight() {
		return weight;
	}

	public VerifyCode setWeight(int weight) {
		this.weight = weight;
		return this;
	}

	public int getHeight() {
		return height;
	}

	public VerifyCode setHeight(int height) {
		this.height = height;
		return this;
	}

	public int getLineNumber() {
		return lineNumber;
	}

	public VerifyCode setLineNumber(int lineNumber) {
		this.lineNumber = lineNumber;
		return this;
	}

	public String getCodes() {
		return codes;
	}

	public VerifyCode setCodes(String codes) {
		this.codes = codes;
		return this;
	}

	public int getR() {
		return r;
	}

	public VerifyCode setR(int r) {
		this.r = r;
		return this;
	}

	public int getG() {
		return g;
	}

	public VerifyCode setG(int g) {
		this.g = g;
		return this;
	}

	public int getB() {
		return b;
	}

	public VerifyCode setB(int b) {
		this.b = b;
		return this;
	}
	
	public int getCharCount() {
		return this.charCount;
	}

	public VerifyCode setCharCount(int charCount) {
		this.charCount = charCount;
		return this;
	}

	public void toDefault(){
		this.weight=100;
		this.height=50;

		this.lineNumber = 6;
		this.charCount = 4;

		this.r = -1;
		this.g = -1;
		this.b = -1;

		this.size = 25;
	}

	private Color randomColor() { 
		if(this.r == -1)
			this.r = this.random.nextInt(100)+150;
		if(this.g == -1)
			this.g = this.random.nextInt(100)+150;
		if(this.b == -1)
			this.b = this.random.nextInt(100)+150;
		return new Color(r,g,b);
	} 
	
	private Font randomFont() { 
		int index=random.nextInt(fontNames.length);
		String fontName=fontNames[index]; 
		int style=random.nextInt(4);
		size=random.nextInt(5)+34;
		return new Font(fontName,style,size);
	} 
		
	private char randomChar() { 
		int index=random.nextInt(codes.length()); 
		return codes.charAt(index); 
	} 
		
	private void drawLine(BufferedImage image) { 
		Graphics2D g = (Graphics2D) image.getGraphics(); 
		for(int i = 0; i < this.lineNumber; i++) { 
			int x1=random.nextInt(weight); 
			int y1=random.nextInt(height); 
			int x2=random.nextInt(weight); 
			int y2=random.nextInt(height); 
			g.setColor(randomColor()); 
			g.drawLine(x1, y1, x2, y2); 
		} 
	} 
	
	private BufferedImage createImage() { 
		BufferedImage image=new BufferedImage(weight,height,BufferedImage.TYPE_INT_RGB); //创建图片缓冲区 
		Graphics2D g=(Graphics2D) image.getGraphics(); //获取画笔 
		g.setColor(Color.GRAY); //设置背景色
		g.fillRect(0, 0, weight, height); 
		return image; //返回一个图片 
	} 

	public VerifyInfo getImage() {
		BufferedImage image=createImage(); 
		Graphics2D g=(Graphics2D) image.getGraphics(); //获取画笔
		StringBuilder sb=new StringBuilder(); 
		for(int i=0;i<this.charCount;i++){ 
			String s=randomChar()+""; //随机生成字符，因为只有画字符串的方法，没有画字符的方法，所以需要将字符变成字符串再画 
			sb.append(s); //添加到StringBuilder里面 
			float x=i*1.0F*weight/this.charCount; //定义字符的x坐标 
			g.setFont(randomFont()); //设置字体，随机
			g.setColor(randomColor()); //设置颜色，随机 
			g.drawString(s, x, height-size/2);
		} 
		String text = sb.toString();
		drawLine(image); 
		return new VerifyInfo(image, text);
	} 
	
	public static void output(BufferedImage image, OutputStream out) throws IOException { 
		ImageIO.write(image, "JPEG", out); 
	}

	public static class VerifyInfo{

	    private BufferedImage bufferedImage;

	    private String text;

	    public VerifyInfo(){}

	    public VerifyInfo(BufferedImage bufferedImage, String text){
	        this.bufferedImage = bufferedImage;
	        this.text = text;
        }

        public BufferedImage getBufferedImage() {
            return bufferedImage;
        }

        public VerifyInfo setBufferedImage(BufferedImage bufferedImage) {
            this.bufferedImage = bufferedImage;
            return this;
        }

        public String getText() {
            return text;
        }

        public VerifyInfo setText(String text) {
            this.text = text;
            return this;
        }
    }
}
